﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;

namespace RENIT.TagsCloud3D.Utils
{
    public class TypeWrapper<T>
    {
        private Type targetType;
        private object instance;
        private Binder binder;
        
        public TypeWrapper(T target)
        {
            targetType = typeof(T);
            instance = target;
            binder = Type.DefaultBinder;
        }

        protected virtual object DoCall(string name, BindingFlags bindingFlags, object[] args)
        {
            return targetType.InvokeMember(name, (instance == null ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.FlattenHierarchy | bindingFlags, binder, instance, args);
        }

        public void InvokeNonPublic(string methodName, object[] args)
        {
            DoCall(methodName, BindingFlags.InvokeMethod | BindingFlags.NonPublic, args);
        }

        protected virtual TResult TryGetPropertyValue<TResult>(string propertyName, TResult defaultValue, bool throwError, params object[] indexerArgs)
        {
            try
            {
                return (TResult)DoCall(propertyName, BindingFlags.GetProperty | BindingFlags.NonPublic, indexerArgs);
            }
            catch(Exception err)
            {
                if (throwError)
                {
                    throw;
                }
                else
                {
                    Trace.WriteLine(err);
                    return defaultValue;
                }
            }
        }

        public virtual TResult TryGetPropertyValue<TResult>(string propertyName, params object[] indexerArgs)
        {
            return TryGetPropertyValue(propertyName, default(TResult), false, indexerArgs);
        }
    }
}
